home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / asm4.zip / SETUP.ASM next >
Assembly Source File  |  1986-04-15  |  28KB  |  569 lines

  1. ;
  2. interrupts    segment at 0h                      ;interrupt table segment
  3.               org 9h*4
  4. keyboard_int  dw 2 dup (?)                       ;interrupt 9 vector
  5. interrupts    ends
  6. ;
  7. rom_bios_data segment at 40h                     ;ROM BIOS data area segment
  8.               org 60h
  9. ;
  10. cursor_mode   dw ?            ;starting and ending cursor scan lines
  11. rom_bios_data ends
  12. ;
  13. rom           segment at 0F000h                  ;ROM segment
  14.               org 0FFFEh
  15. ;
  16. machine_id    db ?                ;ID byte identifies machine as PCjr or other
  17. rom           ends
  18. ;
  19. code          segment para public 'code'         ;code segment
  20.               assume cs:code
  21.               org 100h
  22. ;
  23. begin:        jmp initialize                     ;goto initialization routine
  24. ;
  25.               db '(C) Copyright 1986, Ziff-Davis Publishing Company ', 1Ah
  26. ;
  27. column_count  dw ?                               ;width of window in columns
  28. cursor_type   dw ?                               ;cursor scan line definition
  29. setup_status  db 0          ;indicates if printer window is already active
  30. display_mode  dw ?                               ;current crt display mode
  31. page_no       dw ?                               ;current displayed page
  32. attribute1    db 4Fh                             ;window attribute bytes
  33. attribute2    db 70h
  34. ;
  35. display_table db 2Dh,29h    ;display re-enable values for modes 2 and 3
  36. video         dw 0B800h,0B900h,0BA00h,0BB00h     ;starting addresses of video
  37.                                                  ;memory for CGA pages 0 - 3
  38. ;
  39. mono_video    dw 0B000h                          ;video segment address for
  40.                          ;monochrome adapter
  41. ;
  42. old_kb_int              label dword
  43. old_keyboard_int        dw 2 dup (?)             ;storage for old keyboard
  44.                          ;interrupt vector
  45. ;
  46. ;----------------------------------------------------------------------------
  47. ;Text of the Printer Setup Menu window.
  48. ;After initialization, text and attribute bytes are combined and stored
  49. ;in the WINDOW_TEXT area, and this area is used to store the contents of
  50. ;the screen that underlie the window when the window is called up.
  51. ;----------------------------------------------------------------------------
  52. ;
  53. window_buffer           label word
  54. buffer_text             db 201,26 dup (205),187
  55.                         db 186,'    PRINTER SETUP MENU    ',186
  56.                         db 186,'   EPSON RX/FX PRINTERS   ',186
  57.                         db 199,26 dup (196),182
  58.                         db 186,' F1    Compressed Mode    ',186
  59.                         db 186,' F2    Expanded Mode      ',186
  60.                         db 186,' F3    Emphasized Mode    ',186
  61.                         db 186,' F4    Double-Strike Mode ',186
  62.                         db 186,' F5    Elite Mode         ',186
  63.                         db 186,' F6    Miniature Mode     ',186
  64.                         db 186,' F7    Skip Perforation   ',186
  65.                         db 186,' F8    Indent Left Margin ',186
  66.                         db 186,' F9    Reset Top-of-Form  ',186
  67.                         db 186,' F10   Reset Print Modes  ',186
  68.                         db 186,' ESC   Exit               ',186
  69.                         db 199,26 dup (196),182
  70.                         db 186,' Unshifted:   Toggle ON   ',186
  71.                         db 186,' Shifted:     Toggle OFF  ',186
  72.                         db 200,26 dup (205),188
  73.                         db 532 dup (?)
  74. ;
  75. ;Storage area for the combination of text and attribute bytes that
  76. ;form the window image.
  77. ;
  78. window_bytes  label byte
  79. window_text   dw 532 dup (?)
  80. ;
  81. ;Control code strings for all of the printer setup options.
  82. ;
  83. code_table:   db 15,255,14 dup (0)            ;compressed mode on
  84.               db 27,87,1,255,12 dup (0)                 ;expanded mode on
  85.               db 27,69,255,13 dup (0)                   ;emphasized mode on
  86.               db 27,71,255,13 dup (0)                   ;double-strike mode on
  87.               db 27,77,255,13 dup (0)                   ;elite mode on
  88.               db 15,27,83,0,27,65,6,255,8 dup (0)       ;miniature mode on
  89.               db 27,78,12,255,12 dup (0)                ;perfskip on
  90.               db 27,108,10,255,12 dup (0)               ;indent left margin
  91.               db 27,67,66,255,12 dup (0)                ;reset top-of-form
  92.               db 18,27,87,0,27,70,27,72,27,80,27,84,27,50,255,0      ;reset
  93.                                                                ;print modes
  94. ;
  95.               db 18,255,14 dup (0)                      ;compress off
  96.               db 27,87,0,255,12 dup (0)                 ;expand off
  97.               db 27,70,255,13 dup (0)                   ;emphasize off
  98.               db 27,72,255,13 dup (0)                   ;double-strike off
  99.               db 27,80,255,13 dup (0)                   ;elite off
  100.               db 18,27,84,27,50,255,10 dup (0)          ;miniature off
  101.               db 27,79,255,13 dup (0)                   ;perfskip off
  102.               db 27,108,0,255,12 dup (0)                ;indent off
  103. ;
  104. ;---------------------------------------------------------------------------
  105. ;Execution comes here, to the main body of the program, when an interrupt 9
  106. ;is generated from the keyboard.  Registers are saved, then the keypress is
  107. ;checked and compared to the key combination that activates the menu window.
  108. ;---------------------------------------------------------------------------
  109. ;
  110. main          proc near
  111.               sti                                ;enable software interrupts
  112.               push ax                            ;save all registers
  113.               push bx
  114.               push cx
  115.               push dx
  116.               push si
  117.               push di
  118.               push ds
  119.               push es
  120.               push ax                ;save ax for call to old routine
  121.               in al,0A0h                         ;re-enable NMI on PCjr
  122.               pop ax                             ;restore ax
  123.               pushf          ;simulate interrupt call to old keyboard routine
  124.               call old_kb_int                    ;call old routine
  125.               mov ah,2                   ;check status of the shift keys
  126.               int 16h
  127.               and al,5                           ;Ctrl and Rt-Shift depressed?
  128.               cmp al,5
  129.               je do_program                      ;yes, then skip exit routine
  130. ;
  131. ;Exit routine is the common point of exit for all routines in the program.
  132. ;
  133. exit:         pop es
  134.               pop ds
  135.               pop di
  136.               pop si
  137.               pop dx
  138.               pop cx
  139.               pop bx
  140.               pop ax
  141.               iret
  142. ;
  143. ;Execution comes here when the proper key combination, Ctrl/Rt-Shift, is
  144. ;pressed.  First task is to check whether or not the window is already open.
  145. ;
  146. do_program:   push cs              ;set es and ds to the code segment
  147.               pop ds
  148.               push cs
  149.               pop es
  150.               cmp setup_status,0                 ;is the window already open?
  151.               jne exit                           ;yes, then ignore request
  152. ;
  153. ;----------------------------------------------------------------------------
  154. ;Check current video mode.  If it's mode 2, 3, or 7, then set the window
  155. ;status flag, store the mode number and page number, save the cursor type,
  156. ;and hide the cursor.  If any other display mode is active instead, ignore
  157. ;the request and exit.
  158. ;----------------------------------------------------------------------------
  159. ;
  160.               mov ah,15                          ;get page and mode numbers
  161.               int 10h                            ;al=mode, bh=page
  162.               cmp al,2                ;is crt now in an acceptable mode?
  163.               je prog0                           ;yes, then continue
  164.               cmp al,3
  165.               je prog0
  166.               cmp al,7
  167.               je prog0
  168.               jmp exit                           ;no, then ignore request
  169. prog0:        mov setup_status,1                 ;set status flag to indicate
  170.                                                  ;that window is active
  171.               mov ah,0                           ;save mode number
  172.               mov display_mode,ax
  173.               push bx
  174.               mov bl,bh               ;save page number for color displays
  175.               mov bh,0
  176.               mov page_no,bx
  177.               pop bx
  178.               mov ah,3                           ;get cursor type
  179.               int 10h
  180.               mov cursor_type,cx                 ;save it
  181.               mov ah,1                           ;hide the cursor until later
  182.               mov ch,20h
  183.               int 10h
  184. ;
  185. ;Preparatory routines are completed.  Now open the window by first saving the
  186. ;contents of video memory beneath the window and then writing the window text
  187. ;directly to memory.
  188. ;
  189.               mov bx,page_no             ;use bx as index into video segment
  190.                                          ;address table
  191.               cmp display_mode,7         ;manually adjust index for monochrome
  192.                                          ;adapter
  193.               jne prog1
  194.               mov bx,4
  195. prog1:        shl bx,1                           ;multiply bx by two since
  196.                                                  ;table is made up of words
  197.               mov ax,video[bx]                   ;read segment from table
  198.               mov ds,ax                          ;ds set to video memory
  199.               cmp display_mode,7                 ;skip disable if in mode 7
  200.               je prog2
  201.               call video_disable      ;turn display off for snow-free writing
  202. prog2:        lea di,window_buffer         ;set di to buffer area to save
  203.                                            ;screen contents
  204.               mov ch,28               ;define window dimensions and location
  205.               mov cl,19
  206.               mov dh,2
  207.               mov dl,26
  208.               call video2mem          ;then transfer screen contents to buffer
  209.               push ds                            ;set es to video memory
  210.               pop es
  211.               push cs                            ;reset ds to code segment
  212.               pop ds
  213.               lea si,window_text                 ;point si to window image
  214. prog3:        mov ch,28                          ;define window region
  215.               mov cl,19
  216.               mov dh,2
  217.               mov dl,26
  218.               call mem2video         ;and write the window to the display
  219.               cmp display_mode,7                 ;skip enable if in mode 7
  220.               je getkey
  221.               call video_enable                  ;re-enable the video display
  222. ;
  223. ;Window is now present on the screen, so wait for a keypress.
  224. ;
  225. getkey:      mov ah,0                           ;get a keypress
  226.               int 16h
  227.               cmp al,0                           ;is it an extended code?
  228.               je extended_code                   ;yes, go interpret it
  229.               cmp al,27                          ;is it the ESC key?
  230.               jne getkey1           ;no, then signal illegal keypress
  231. ;
  232. ;----------------------------------------------------------------------------
  233. ;Execution comes here when the ESC key is pressed.  The window is refilled
  234. ;with its original contents, the cursor is restored, and control is handed
  235. ;back to the application program.
  236. ;----------------------------------------------------------------------------
  237. ;
  238.               cmp display_mode,7                 ;skip disable if in mode 7
  239.               je prog4
  240.               call video_disable                 ;turn off the display
  241. prog4:        lea si,window_buffer               ;point si to the buffer area
  242.               mov ch,28                          ;define the window
  243.               mov cl,19
  244.               mov dh,2
  245.               mov dl,26
  246.               call mem2video     ;and write the buffer contents to the display
  247.               cmp display_mode,7                 ;skip enable if in mode 7
  248.               je prog5
  249.               call video_enable                  ;turn display back on
  250. prog5:        mov ah,1                           ;restore cursor
  251.               mov cx,cursor_type
  252.               int 10h
  253.               mov setup_status,0                 ;reset window status
  254.               jmp exit                           ;and exit
  255. ;
  256. ;Getkey1 routine handles an illegal keypress by beeping and returning
  257. ;for another.
  258. ;
  259. getkey1:      call beep              ;beep and return for another keypress
  260.               jmp getkey
  261. ;
  262. ;An extended code has been entered...check its validity and goto the
  263. ;appropriate routine.
  264. ;
  265. extended_code:
  266.               cmp ah,59                          ;less than F1?
  267.               jb getkey1                         ;yes, then don't accept it
  268.               cmp ah,91                          ;greater than Shft-F8?
  269.               ja getkey1                         ;yes, then don't accept it
  270.               cmp ah,68                          ;between F1 and F10?
  271.               jbe unshifted                      ;yes
  272.               cmp ah,84                          ;between Shft-F1 and Shft-F9?
  273.               jae shifted                        ;yes
  274.               jmp getkey1     ;if all tests failed, then keypress was illegal
  275. ;
  276. ;----------------------------------------------------------------------------
  277. ;If a legal function key was pressed, its scan code is translated here to the
  278. ;starting address of the string of bytes to be sent to the printer.  The
  279. ;string is then sent to LPT1: provided it's powered on and on-line.
  280. ;----------------------------------------------------------------------------
  281. ;
  282. shifted:      sub ah,15               ;adjustment for shifted function keys
  283. unshifted:    sub ah,59                ;adjustment for unshifted function keys
  284.               mov al,ah                          ;convert index to word in ax
  285.               xor ah,ah
  286.               mov cl,4                           ;multiply ax by 16
  287.               shl ax,cl
  288.               add ax,offset code_table     ;convert ax to full offset address
  289.               mov si,ax                          ;and transfer it to si
  290.               call lpt1stat                      ;check for printer ready
  291.               jc getkey1                         ;beep if printer not ready
  292.               mov bl,255               ;specify delimiter for call to LPRINTZ
  293.               call lprintz             ;send control code string to printer
  294.               jmp getkey                         ;return for another keypress
  295. ;
  296. main          endp                               ;end of main body of program
  297. ;
  298. ;---------------------------------------------------------------------------
  299. ;VIDEO_ENABLE and VIDEO_DISABLE routines manipulate bit 3 of port 3D8h,
  300. ;the CGA Mode Control Register, to temporarily turn the display on or off.
  301. ;Since these routines write directly to hardware, they have no effect on
  302. ;other video adapters.
  303. ;---------------------------------------------------------------------------
  304. ;
  305. video_disable proc near
  306.               mov dx,3DAh                        ;read CGA status port
  307. disable1:     in al,dx               ;wait for vertical retrace to occur
  308.               test al,8                          ;is bit 3 set?
  309.               je disable1                        ;no, wait until it is
  310.               mov dx,3D8h                        ;now disable the display
  311.               mov al,25h      ;by clearing bit 3 of the Mode Control Register
  312.               out dx,al
  313.               ret
  314. video_disable endp
  315. ;
  316. video_enable  proc near
  317.               mov dx,3D8h                        ;CGA Mode Control Register
  318.               mov bx,display_mode        ;get value to re-enable display
  319.               sub bx,2
  320.               mov al,display_table[bx]
  321.               out dx,al                          ;and send it to the port
  322.               ret
  323. video_enable  endp
  324. ;
  325. ;---------------------------------------------------------------------------
  326. ;VIDEO2MEM routine transfers the contents of a portion of video memory
  327. ;to a memory buffer for storage.
  328. ;Entry:       DS    - video segment
  329. ;             ES:DI - memory buffer
  330. ;             DH,DL - row and column of upper left corner of window
  331. ;             CH    - width of window in columns
  332. ;             CL    - number of lines in window
  333. ;---------------------------------------------------------------------------
  334. ;
  335. video2mem     proc near
  336.               mov al,ch                          ;store number of columns
  337.               mov ah,0
  338.               mov column_count,ax
  339.               mov ch,0                           ;cx = number of lines
  340.               push di                            ;save di
  341.               call video_offset        ;get cell address of first character
  342.               mov si,di                          ;put it in si
  343.               pop di                             ;restore di
  344. v2mem1:       push si                            ;save si for next line
  345.               push cx                            ;save line count
  346.               mov cx,column_count                ;set cx for call to WRITELN
  347.               call writeln                       ;transfer one line
  348.               pop cx                             ;restore saved registers
  349.               pop si
  350.               add si,160                         ;set si for next line address
  351.               loop v2mem1                ;loop until all lines are done
  352.               ret
  353. video2mem     endp
  354. ;
  355. ;---------------------------------------------------------------------------
  356. ;MEM2VIDEO writes a selected area of memory to the video display.
  357. ;Entry:       DS:SI - memory buffer
  358. ;             ES    - video segment
  359. ;             DH,DL - row and column of upper left corner of window
  360. ;             CH    - width of window in columns
  361. ;             CL    - number of lines in window
  362. ;---------------------------------------------------------------------------
  363. ;
  364. mem2video     proc near
  365.               mov al,ch                          ;save number of columns
  366.               mov ah,0
  367.               mov column_count,ax
  368.               mov ch,0                           ;cx = number of lines
  369.               call video_offset                  ;get offset into video memory
  370. mem2v1:       push di                            ;save video starting address
  371.               push cx                            ;save line count
  372.               mov cx,column_count                ;set cx for call to WRITELN
  373.               call writeln                       ;transfer one line
  374.               pop cx                             ;restore registers
  375.               pop di
  376.               add di,160                         ;set di for next display line
  377.               loop mem2v1                        ;loop until done
  378.               ret
  379. mem2video     endp
  380. ;
  381. ;---------------------------------------------------------------------------
  382. ;VIDEO_OFFSET calculates the offset into video memory of a character cell.
  383. ;Entry:       DH,DL - row and column of cell (0-24,0-79)
  384. ;Exit:        DI    - offset address
  385. ;---------------------------------------------------------------------------
  386. ;
  387. video_offset  proc near
  388.               mov al,160
  389.               mul dh                             ;row * 160
  390.               shl dl,1                           ;column * 2
  391.               mov dh,0                           ;byte to word
  392.               add ax,dx                          ;(row *160)+(column*2)
  393.               mov di,ax                          ;set offset in di
  394.               ret
  395. video_offset  endp
  396. ;
  397. ;---------------------------------------------------------------------------
  398. ;WRITELN subroutine copies a string of words from one memory location to
  399. ;another.  The CGA status port is not checked for vertical retrace status
  400. ;before transfer.
  401. ;Entry:       DS:SI - source
  402. ;             ES:DI - destination
  403. ;             CX    - number of words
  404. ;---------------------------------------------------------------------------
  405. ;
  406. writeln       proc near
  407.               cld                     ;clear for string instructions
  408. write1:       movsw                              ;move one word
  409.               loop write1                        ;loop until done
  410.               ret
  411. writeln       endp
  412. ;
  413. ;---------------------------------------------------------------------------
  414. ;LPRINTZ routine sends a string of bytes delimited by a user-specified byte to
  415. ;LPT1: thru INT 17h.
  416. ;Entry:       DS:SI - string address
  417. ;             BL    - delimiter (0-255)
  418. ;---------------------------------------------------------------------------
  419. ;
  420. lprintz       proc near
  421.               cld                                ;for 8088 string instructions
  422. lprintz1:     lodsb                              ;get one byte
  423.               cmp al,bl                          ;is it the delimiter?
  424.               je lprintz2                        ;yes, then exit
  425.               mov dx,0                           ;printer no. 0 (LPT1:)
  426.               mov ah,0
  427.               int 17h                            ;send byte to printer
  428.               jmp lprintz1                       ;return for next byte
  429. lprintz2:     ret
  430. lprintz       endp
  431. ;
  432. ;---------------------------------------------------------------------------
  433. ;LPT1STAT checks the current status of printer LPT1:.  If it's either
  434. ;powered off or off-line, then an error condition is signalled upon return
  435. ;thru the carry flag.
  436. ;Exit:        Carry clear - no error
  437. ;             Carry set   - error
  438. ;---------------------------------------------------------------------------
  439. ;
  440. lpt1stat      proc near
  441.               mov dx,0                  ;printer no. 0
  442.               mov ah,2               ;use ROM BIOS 'get status' function
  443.               int 17h
  444.               test ah,8                 ;test bit 3, I/O error indicator
  445.               je stat1                  ;if clear, then no error
  446.               stc                       ;raise error flag
  447.               ret
  448. stat1:        clc                       ;clear error flag
  449.               ret
  450. lpt1stat      endp
  451. ;
  452. ;---------------------------------------------------------------------------
  453. ;BEEP uses the 8253 timer chip to emit a short beep thru the PC's speaker.
  454. ;---------------------------------------------------------------------------
  455. ;
  456. beep          proc near
  457.               mov al,182             ;notify 8253 that frequency data is coming
  458.               out 67,al
  459.               mov al,0                           ;send frequency (776.8 Hz)
  460.               out 66,al
  461.               mov al,6
  462.               out 66,al
  463.               in al,97                           ;activate speaker
  464.               or al,3
  465.               out 97,al
  466.               mov cx,6000h                 ;time delay for sound duration
  467. beep1:        loop beep1
  468.               in al,97                           ;deactivate speaker
  469.               and al,252
  470.               out 97,al
  471.               ret
  472. beep          endp
  473. ;
  474. ;---------------------------------------------------------------------------
  475. ;MEM2MEM subroutine transfers a non-overlapping block of memory one byte
  476. ;at a time.
  477. ;Entry:       DS:SI - source
  478. ;             ES:DI - destination
  479. ;             CX    - number of bytes
  480. ;---------------------------------------------------------------------------
  481. ;
  482. mem2mem       proc near
  483.               cld
  484. mem1:         movsb                              ;transfer one byte
  485.               loop mem1                          ;and loop until done
  486.               ret
  487. mem2mem       endp
  488. ;
  489. ;---------------------------------------------------------------------------
  490. ;Initialization routine sets up the window image in the WINDOW_TEXT area,
  491. ;resets the CURSOR_MODE word if this is a PCjr, and saves and replaces the
  492. ;old keyboard interrupt vector.
  493. ;---------------------------------------------------------------------------
  494. ;
  495. initialize    proc near
  496. ;
  497. ;Initialize the window text area by combining the text data with the attribute
  498. ;bytes and placing the conglomeration in the WINDOW_TEXT area.
  499. ;
  500.               assume ds:code,es:code
  501.               mov ah,15                          ;check the current video mode
  502.               int 10h
  503.               cmp al,7              ;if it's mode 7, then replace the attribute
  504.               jne init0          ;bytes with ones appropriate for mono adapter
  505.               mov attribute1,70h
  506.               mov attribute2,07h
  507. init0:        cld              ;now combine the text and attribute bytes
  508.               lea si,buffer_text                 ;point si to table of text
  509.               lea di,window_bytes                ;and di to storage area
  510.               mov cx,112           ;create first four lines by combining
  511.               mov al,attribute1          ;text with attribute1 (112 words)
  512. init1:        movsb                              ;text byte
  513.               stosb                              ;attribute byte
  514.               loop init1                 ;loop until all 112 words are done
  515.               mov cx,11                          ;now do the next 11 lines
  516. init2:        push cx              ;first attribute in each line is attribute1
  517.               movsb
  518.               stosb
  519.               mov cx,26            ;next 26 attributes are attribute2
  520.               mov al,attribute2
  521. init3:        movsb
  522.               stosb
  523.               loop init3
  524.               movsb
  525.               mov al,attribute1     ;and the last in each line is attribute1
  526.               stosb
  527.               pop cx
  528.               loop init2            ;loop until all 11 lines are done
  529.               mov cx,112            ;create the last four lines just like
  530. init4:        movsb                 ;the first four
  531.               stosb
  532.               loop init4
  533. ;
  534. ;Check the machine ID byte in ROM and if this is a PCjr, then reset the
  535. ;cursor and correct the CURSOR_MODE word at 0040:0060.
  536. ;
  537.               mov ax,rom                         ;set ds to rom
  538.               mov ds,ax
  539.               assume ds:rom
  540.               cmp machine_id,0FDh                ;is this a PCjr?
  541.               jne init5                          ;no, then skip this routine
  542.               mov ax,rom_bios_data               ;set ds to ROM BIOS data area
  543.               mov ds,ax
  544.               assume ds:rom_bios_data
  545.               mov cursor_mode,0607h          ;reset the cursor mode indicator
  546.               mov ah,1                       ;then physically reset the cursor
  547.               mov cx,0607h
  548.               int 10h
  549. ;
  550. ;Now save the old keyboard interrupt vector and replace it with the new one.
  551. ;
  552. init5:        mov ax,interrupts          ;set ds to the interrupt vector area
  553.               mov ds,ax
  554.               assume ds:interrupts
  555.               mov ax,keyboard_int                ;save old vector
  556.               mov old_keyboard_int,ax
  557.               mov ax,keyboard_int[2]
  558.               mov old_keyboard_int[2],ax
  559.               cli                        ;disable all interrupts but NMI
  560.               mov keyboard_int,offset main       ;and install new vector
  561.               mov keyboard_int[2],cs
  562.               sti                                ;re-enable interrupts
  563.               mov dx,offset initialize   ;point dx to end of resident section
  564.               int 27h                            ;terminate-but-stay-resident
  565. initialize    endp
  566. ;
  567. code          ends
  568.               end begin
  569.